package mn.idax.exchange.otc.service.impl;

import mn.idax.exchange.common.CalendarUtil;
import mn.idax.exchange.otc.entity.Account;
import mn.idax.exchange.otc.entity.AccountTransaction;
import mn.idax.exchange.otc.entity.OTCOrder;
import mn.idax.exchange.otc.enums.AccountTransactionEnum;
import mn.idax.exchange.otc.enums.response.OrderResponseEnum;
import mn.idax.exchange.otc.exception.IdaxException;
import mn.idax.exchange.otc.mapper.AccountTransactionMapper;
import mn.idax.exchange.otc.service.AccountService;
import mn.idax.exchange.otc.service.AccountTransactionService;
import mn.idax.exchange.otc.service.OTCOrderService;
import mn.idax.exchange.otc.util.DateUtils;
import mn.idax.exchange.otc.util.UUidUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

/**
 * Create by jack_huang on 2018/8/19
 */
@Service
public class AccountTransactionServiceImpl implements AccountTransactionService {

    /**
     *
     下单：   卖方可用-， 冻结+
     成交：   卖方可用不变，冻结-； 买方可用+，冻结不变
     超时取消： 卖方可用+， 冻结-
     */
    @Autowired
    private AccountTransactionMapper accountTransactionMapper;

    @Autowired
    private OTCOrderService otcOrderService;

    @Autowired
    private AccountService accountService;

    //下单时调
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED,rollbackFor = {RuntimeException.class,Exception.class})
    public Boolean insertAccountTransactionCreateOrder(Integer transactiontype,OTCOrder order) {

        if (order == null){
            throw new IdaxException(OrderResponseEnum.ORDER_ISNOTEXIST.getRespCode());
        }
        Integer seller = order.getSeller();
        Account account = accountService.getAccountByCoinIdAndUserId(seller, order.getCoinid());
        if (account == null){
            throw new IdaxException(OrderResponseEnum.ACCOUNT_ISNOTEXOST.getRespCode());
        }

        AccountTransaction accountTransaction = new AccountTransaction();

        accountTransaction.setId(UUidUtils.getGUID());
        accountTransaction.setAccountid(account.getId());
        accountTransaction.setUserid(seller);
        accountTransaction.setTransactiontype(transactiontype);

        accountTransaction.setAvailablechange(order.getQty().multiply(new BigDecimal(-1)));
        accountTransaction.setFrozenchange(order.getQty());

        accountTransaction.setAccountavailableamount(account.getAvailableamount());
        accountTransaction.setAccountfrozenamount(account.getFrozenamount());
        accountTransaction.setAccountamount(account.getAvailableamount().add(account.getFrozenamount()));
        accountTransaction.setRemark(AccountTransactionEnum.getRemark(transactiontype));
        accountTransaction.setCoincode(order.getPairname());
        accountTransaction.setCreatetime(DateUtils.getCalendarToDate(CalendarUtil.getUTCDate(new Date())));
        accountTransaction.setUpdatetime( accountTransaction.getCreatetime());

        return accountTransactionMapper.insertSelective(accountTransaction) == 1;
    }

    @Override
    public Boolean insertAccountTransactionCancelOrder(Integer transactiontype,OTCOrder order) {
        if (order == null){
            throw new IdaxException(OrderResponseEnum.ORDER_ISNOTEXIST.getRespCode());
        }
        Integer seller = order.getSeller();
        Account account = accountService.getAccountByCoinIdAndUserId(seller, order.getCoinid());
        if (account == null){
            throw new IdaxException(OrderResponseEnum.ACCOUNT_ISNOTEXOST.getRespCode());
        }

        AccountTransaction accountTransaction = new AccountTransaction();

        accountTransaction.setId(UUidUtils.getGUID());
        accountTransaction.setAccountid(account.getId());
        accountTransaction.setUserid(seller);
        accountTransaction.setTransactiontype(transactiontype);

        accountTransaction.setAvailablechange(order.getQty());
        accountTransaction.setFrozenchange(order.getQty().multiply(new BigDecimal(-1)));

        accountTransaction.setAccountavailableamount(account.getAvailableamount());
        accountTransaction.setAccountfrozenamount(account.getFrozenamount());
        accountTransaction.setAccountamount(account.getAvailableamount().add(account.getFrozenamount()));
        accountTransaction.setRemark(AccountTransactionEnum.getRemark(transactiontype));
        accountTransaction.setCoincode(order.getPairname());
        accountTransaction.setCreatetime(DateUtils.getCalendarToDate(CalendarUtil.getUTCDate(new Date())));
        accountTransaction.setUpdatetime( accountTransaction.getCreatetime());

        return accountTransactionMapper.insertSelective(accountTransaction) == 1;
    }

    @Override
    public Boolean insertAccountTransactionReleaseOrder(Integer transactiontype, OTCOrder order) {
        if (order == null){
            throw new IdaxException(OrderResponseEnum.ORDER_ISNOTEXIST.getRespCode());
        }
        Integer buyer = order.getBuyer();
        Integer seller = order.getSeller();

        Account buyerAccount = accountService.getAccountByCoinIdAndUserId(buyer, order.getCoinid());
        if (buyerAccount == null){
            throw new IdaxException(OrderResponseEnum.ACCOUNT_ISNOTEXOST.getRespCode());
        }

        Account sellerAccount = accountService.getAccountByCoinIdAndUserId(seller, order.getCoinid());
        if (sellerAccount == null){
            throw new IdaxException(OrderResponseEnum.ACCOUNT_ISNOTEXOST.getRespCode());
        }

        //买家流水插入
        AccountTransaction buyerAccountTransaction = new AccountTransaction();
        buyerAccountTransaction.setId(UUidUtils.getGUID());
        buyerAccountTransaction.setAccountid(buyerAccount.getId());
        buyerAccountTransaction.setUserid(buyer);
        buyerAccountTransaction.setTransactiontype(transactiontype);

        buyerAccountTransaction.setAvailablechange(order.getQty());
        buyerAccountTransaction.setFrozenchange(BigDecimal.ZERO);

        buyerAccountTransaction.setAccountavailableamount(buyerAccount.getAvailableamount());
        buyerAccountTransaction.setAccountfrozenamount(buyerAccount.getFrozenamount());
        buyerAccountTransaction.setAccountamount(buyerAccount.getAvailableamount().add(buyerAccount.getFrozenamount()));
        buyerAccountTransaction.setRemark(AccountTransactionEnum.getRemark(transactiontype));
        buyerAccountTransaction.setCoincode(order.getPairname());
        buyerAccountTransaction.setCreatetime(DateUtils.getCalendarToDate(CalendarUtil.getUTCDate(new Date())));
        buyerAccountTransaction.setUpdatetime( buyerAccountTransaction.getCreatetime());

        int buy = accountTransactionMapper.insertSelective(buyerAccountTransaction);

        //卖家流水插入
        AccountTransaction sellerAccountTransaction = new AccountTransaction();

        sellerAccountTransaction.setId(UUidUtils.getGUID());
        sellerAccountTransaction.setAccountid(sellerAccount.getId());
        sellerAccountTransaction.setUserid(seller);
        sellerAccountTransaction.setTransactiontype(transactiontype);

        sellerAccountTransaction.setAvailablechange(BigDecimal.ZERO);
        sellerAccountTransaction.setFrozenchange(order.getQty().multiply(new BigDecimal(-1)));

        sellerAccountTransaction.setAccountavailableamount(sellerAccount.getAvailableamount());
        sellerAccountTransaction.setAccountfrozenamount(sellerAccount.getFrozenamount());
        sellerAccountTransaction.setAccountamount(sellerAccount.getAvailableamount().add(sellerAccount.getFrozenamount()));
        sellerAccountTransaction.setRemark(AccountTransactionEnum.getRemark(transactiontype));
        sellerAccountTransaction.setCoincode(order.getPairname());
        sellerAccountTransaction.setCreatetime(DateUtils.getCalendarToDate(CalendarUtil.getUTCDate(new Date())));
        sellerAccountTransaction.setUpdatetime( sellerAccountTransaction.getCreatetime());

        int sell = accountTransactionMapper.insertSelective(sellerAccountTransaction);
        return buy == 1 && sell == 1;
    }
}
